package com.gssbh.framework.toolkit.mybatis;

import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.*;
import com.gssbh.framework.toolkit.configuration.DataCenterProperties;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.util.Objects;


/**
 * mybatis/ mybatis-plus configuration
 *
 * @author witkey9876@qq.com
 */
@Configuration
@AutoConfigureAfter({MybatisPlusAutoConfiguration.class})
@EnableConfigurationProperties({DataCenterProperties.class})
public class MyBatisToolkitAutoConfiguration {


    /**
     * 新多租户插件配置,一缓和二缓遵循mybatis的规则,需要设置
     * MybatisConfiguration#useDeprecatedExecutor = false 避免缓存万一出现问题
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
            @Override
            public Expression getTenantId() {
                return new LongValue(1);
            }

            // 这是 default 方法,默认返回 false 表示所有表都需要拼多租户条件
            @Override
            public boolean ignoreTable(String tableName) {
                return false;
            }

            @Override
            public String getTenantIdColumn() {
                return TenantLineHandler.super.getTenantIdColumn();
            }
        }));
        // 如果用了分页插件注意先 add TenantLineInnerInterceptor 再 add PaginationInnerInterceptor
        // 用了分页插件必须设置 MybatisConfiguration#useDeprecatedExecutor = false
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());

        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor(true));

        interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
        // 有bug,不能直接使用
//        interceptor.addInnerInterceptor(new IllegalSQLInnerInterceptor());

        interceptor.addInnerInterceptor(new DataPermissionInterceptor(new DataPermissionHandler() {
            @Override
            public Expression getSqlSegment(Expression where, String mappedStatementId) {
                return null;
            }
        }));
        return interceptor;
    }

    @Autowired
    DataSource dataSource;
    //


    @Bean
    public DefaultIdentifierGenerator customIdentifierGenerator(@Autowired DataCenterProperties properties) {

        return new DefaultIdentifierGenerator(properties.workerId(), properties.id()) {
           private final NumberGenerator numberGenerator = new NumberGenerator();
            @Override
            public Long nextId(Object entity) {

                if (Objects.nonNull(entity.getClass().getAnnotation(NumberGeneratorIdAnnotation.class))) {
                    TableName tableName = entity.getClass().getAnnotation(TableName.class);
                    if(Objects.isNull(tableName) || tableName.schema().isEmpty()){
                        throw  new RuntimeException("Please follow the guidelines when writing code ");
                    }
                    return NumberGeneratorIdUtils.getNext(tableName.schema()
                            .replaceAll("`","")+","
                            +tableName.value().replaceAll("`","")
                            +","+1,dataSource);
                }else {
                    return super.nextId(entity);
                }
            }
        };
    }

}
